如何在 .NET 使用 AutoMapper
TLDR
- AutoMapper 透過 Reflection 簡化 DTO 與 Entity 之間的屬性賦值,減少重複程式碼。
MapperConfiguration應維持單例(Singleton),建議在應用程式啟動時(如Program.cs)進行配置。- 務必使用
config.AssertConfigurationIsValid()驗證映射設定,確保所有 Destination 欄位皆有對應來源。 - 使用
Profile類別將映射邏輯模組化,避免配置過於龐大。 - 針對複雜映射,可透過
ForMember進行條件判斷、忽略欄位或自定義轉換邏輯。 - 使用
ReverseMap()可簡化雙向轉換,但需注意複雜邏輯需搭配ForPath定義反向規則。 - 整合 Dependency Injection 需安裝
AutoMapper.Extensions.Microsoft.DependencyInjection套件。
AutoMapper 基礎配置與驗證
在 .NET 應用程式中,為了實現關注點分離,常需在不同層級間轉換 DTO。AutoMapper 透過 MapperConfiguration 定義映射規則,並透過 IMapper 執行轉換。
核心使用方式
什麼情況下會遇到這個問題:當需要將一個物件的屬性值複製到另一個型別的物件時。
csharp
// 建立 Configuration 設定 class 之間的映射關係
var config = new MapperConfiguration(cfg => {
cfg.CreateMap<Order, OrderDto>();
});
// 驗證 Configuration 的設置,若 Destination 有的 Member 在 Source 找不到對應,會拋出 AutoMapperConfigurationException
config.AssertConfigurationIsValid();
// 建立 Mapper
var mapper = config.CreateMapper();
// 執行映射
var dest = mapper.Map<Destination>(source);映射規則設定
為了保持程式碼整潔,建議將映射設定封裝於 Profile 類別中。
模組化設定
什麼情況下會遇到這個問題:當專案中存在大量類別映射,導致 Program.cs 或 Startup.cs 過於臃腫時。
csharp
public class OtherProfile : Profile {
public OtherProfile() {
CreateMap<Source1, Destination1>();
// 全域型別轉換(例如:統一處理字串去空白)
CreateMap<string?, string?>().ConvertUsing(x => x == null ? x : x.Trim());
}
}屬性映射進階控制
什麼情況下會遇到這個問題:當 Source 與 Destination 的屬性名稱不一致,或需要根據特定條件決定是否映射時。
csharp
var config = new MapperConfiguration(cfg => {
cfg.CreateMap<Source, Destination>()
// 忽略特定欄位
.ForMember(desc => desc.Prop1, opt => opt.Ignore())
// 指定欄位對應
.ForMember(dest => dest.DestProp2, opt => opt.MapFrom(src => src.SourceProp2))
// 設定條件映射
.ForMember(dest => dest.IntProp4, opt => opt.Condition(src => (src.IntProp4 >= 0)))
// 設定預設值
.ForMember(dest => dest.Prop5, opt => opt.NullSubstitute("Other Value"));
});反向映射與注意事項
使用 ReverseMap() 可以快速建立雙向映射,但需注意以下限制:
- 複雜的轉換邏輯需使用
ForPath定義反向規則。 AssertConfigurationIsValid()無法驗證反向映射的正確性。
csharp
var config = new MapperConfiguration(cfg => {
cfg.CreateMap<Source, Destination>()
.ForMember(dest => dest.Prop5, opt => opt.MapFrom(src => src.Prop3 + "," + src.Prop4))
.ReverseMap()
.ForPath(s => s.Prop3, opt => opt.MapFrom(src => src.Prop5.Split(',')[0]));
});整合 Dependency Injection
什麼情況下會遇到這個問題:在現代 .NET 應用程式中,需要透過 DI 容器管理 IMapper 實例。
需安裝 NuGet 套件 AutoMapper.Extensions.Microsoft.DependencyInjection。
csharp
// 在 Program.cs 中註冊
builder.Services.AddAutoMapper(typeof(Program));
// 在 Controller 或 Service 中使用
public class EmployeesController {
private readonly IMapper _mapper;
public EmployeesController(IMapper mapper) => _mapper = mapper;
}異動歷程
- 2022-10-24 初版文件建立。
